package datamodels;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import org.json.*;
/**
 * Design: Thank to GROUP 5
 * A conference class. Containing a list of manuscript submitted by the author
 * a List of users.  
 * 
 * @author Rithy Chhen, Alan Meaker, Zach Turk and Anthony Sierra
 * @version 11.15.2011
 */
public class Conference {
	/**
	 * THIS IS AN IMPORTANT VARIABLE. WHEN TESTING AND NEED FAKE DATA USE IT AND SET IT TO YES!
	 */
	private boolean test_data_on = true;
	/** 
	 * a list contains all manuscript in a conference.
	 */
	private List<Manuscript> my_manuscript_list;
	/**
	 * a list contains all users in the conference.
	 */
	private List<User> my_user_list;
	/**name of the conference**/
	private String my_name;
	/** 
	 * a user.
	 */
	private User my_user;
	/**
	 * constructor of conference. Create a conference object.
	 */
	public Conference() {
		my_manuscript_list = new ArrayList<Manuscript>();
		my_user_list = new ArrayList<User>();
		my_user = new User();
	}
	/**
	 * Constructs a conference with a specific name for loading data
	 * if the conference has already been created.
	 * 
	 * precondition: my_user_list == NULL
	 * postcondition: user != NULL
	 * @return Conference constructed conference object
	 * @param the_conference_name
	 */
	public Conference(String the_conference_name) {
		my_name = the_conference_name;
		my_manuscript_list = new ArrayList<Manuscript>();
		my_user_list = new ArrayList<User>();
		my_user = new User();
		try {
			instantiateConference(the_conference_name);
		} catch (FileNotFoundException e) {
			System.out.println("Unable to find the file :( <- Sad face");
		}
	}
	/**get conference name**/
	public String getName() {
		return my_name;
	}
	public void removeUserByName(String the_name)
	{
		for (int i = 0; i < my_user_list.size(); i++)
		{
			if (my_user_list.get(i).getName().equals(the_name))
			{
				my_user_list.remove(i);
				break;
			}
		}
	}
	/**
	 *  precondition: the_user != NULL && the_text != NULL && 
	 *  			  the_user.getCurrentRole() == role.AUTHOR.
	 *	postcondition:  my_manuscript_list.size() == old(size) + 1.
	 * @author Rithy Chhen
	 * @version 11.20.2011
	 * @param the_user the user
	 * @param the_text the content of the manuscript is to be added.
	 */
	public void addManuscript(final User the_user, String the_text) {
		Manuscript man = new Manuscript(the_user, the_text);
		my_manuscript_list.add(man);
	}
	/**remove a manuscript from the list*/
	public void removeManuscript(Manuscript the_man) {
		my_manuscript_list.remove(the_man);
		
	}
	/** 
	 * add manuscript using a manuscript object.
	 */
	public void addMan(Manuscript the_man) {
		my_manuscript_list.add(the_man);
	}

	/**get user. */
	public User getUser() {
		return my_user;
	}
	/** 
	 * precondition: the_user != NULL.
	 * 
	 */
	/**
	 * Assigned reviewer to manuscript. 
	 */
	public void AssignReviewers() {
		//TODO
	}
	/**get the manuscript list.
	*	precondition: size <= 0 
	*	@return a list of manuscript in this conference.
	*/
	public List<Manuscript> getManuscripts() {
		return my_manuscript_list;
	}
	/**
	 * get Users. 
	 * precondition: size <= 0
	 * 
	 * @return a list of user in this conference.
	 */
	public List<User> getUsers() {
		
		return my_user_list;
	}
	
	
	// ************ TEMPORARY ***************
	// ***** FOR TESTING PURPOSES ONLY ******
	public void setManList(List<Manuscript> the_man_list)
	{
		for(int i = 0; i < the_man_list.size(); i++)
		{
			my_manuscript_list.add(the_man_list.get(i));
		}
	}
	
	public void addUser(final User the_user)
	{
		my_user_list.add(the_user);
	}
		
	/**
	 * Returns a list of all the manuscripts in the conference that are
	 * written by the requested author. 
	 * 
	 * @author Alan Meaker
	 * @version 11.17.2011
	 * 
	 * @param	the_author The author to get all manuscripts for
	 * @return	List of all manuscripts by requested author
	 * 
	 * @pre		the_author != null
	 * @pre		the_author is an author (the_author.getRole == Role.AUTHOR)
	 * @post	All manuscripts returned are written by the requested author.
	 */
	public List<Manuscript> getManuscriptsByAuthor(final User the_author)
	{
		//create a list of manuscripts to hold all the manuscripts requested
		List<Manuscript> manuscriptList = new ArrayList<Manuscript>();
		
		//iterate over all manuscripts in the conference
		for(Manuscript man : my_manuscript_list )
		{
			//if manuscript was created by author we want
			if(man.getAuthor().equals(the_author))
			{
				//add the manuscript to the list
				manuscriptList.add(man);
			}
		}
		
		//return the list of all manuscripts by the requested author
		return manuscriptList;
	}
	/**
	 * This method will add onto the previous JSON file that was read in in order to create a conference object in the JSON file.
	 * @param the_conference_name The name of the new conference being added.
	 * @return boolean for either the conference by that name exists or that the conference couldnt be created.
	 * @throws FileNotFoundException 
	 */
	public boolean addConference(String the_conference_name) throws FileNotFoundException
	{
		//This runs a check to see if the conference exists already by this name.
		//IF a conference by this name already exists then we return false.
		if (instantiateConference(the_conference_name))
		{
			return false;
		}
		else
		{
			//Text for reading in what might have been there previously in the JSON file.
			StringBuilder text =
				new StringBuilder();
			//Get a scanner and depending on whether we are testing or not use the following files.
			Scanner scanner;
			if (test_data_on)
			{
				scanner =
					new Scanner(new FileInputStream("src/datamodels/conferencesinformation.txt"), "UTF-8");	
			}
			else
			{
				scanner =
					new Scanner(new FileInputStream("src/datamodels/datafile.txt"), "UTF-8");		
			}
			try {
				while (scanner.hasNextLine()){
					text.append(scanner.nextLine());
				}
				//So now at this point we have the previous data file in the text. 
				//Now we need to create a substring conference containing a setup JSON file of what creating a conference looks like
				//and insert it right before the closing curly bracket of the JSON file
				StringBuilder sub_text = new StringBuilder();
				sub_text.append(",\"" + the_conference_name + "\":");//append "conference_name":
				sub_text.append("{}");//append opening and curly bracket for information to be placed later.
				text.replace(text.length()-1, text.length()-1, sub_text.toString());
				//Add it in at the end of the file :)
				
				if (test_data_on)
				{
					Writer out = new OutputStreamWriter(new FileOutputStream("src/datamodels/conferencesinformation.txt"), "UTF-8");
				    try {
				        out.write(text.toString());
				      }
				      finally {
				        out.close();
				      }	
				}
				else
				{
					Writer out = new OutputStreamWriter(new FileOutputStream("src/datamodels/datafile.txt"), "UTF-8");
				    try {
				        out.write(text.toString());
				      }
				      finally {
				        out.close();
				      }	
				}
			}
			catch(Exception e)
			{
				System.out.println("BRoke");
				return false;
			}
			finally{
				scanner.close();
			}
			//Now we need to add the name to the list of conferences in our name reference file.
			StringBuilder names_text = new StringBuilder();
			//Get a scanner and depending on whether we are testing or not use the following files.
			if (test_data_on)
			{
				scanner =
					new Scanner(new FileInputStream("src/datamodels/conferencenames.txt"), "UTF-8");	
			}
			else
			{
				scanner =
					new Scanner(new FileInputStream("src/datamodels/namesdatafile.txt"), "UTF-8");		
			}
			try {
				while (scanner.hasNextLine()){
					names_text.append(scanner.nextLine());
				}
				//So now at this point we have the previous data file in the text. 
				//Now we need to create a substring conference containing a setup JSON file of what creating a conference looks like
				//and insert it right before the closing curly bracket of the JSON file
				StringBuilder sub_text = new StringBuilder();
				sub_text.append(",\"" + "name" + "\":");
				sub_text.append(",\"" + the_conference_name + "\"");//append "conference_name":
				text.replace(names_text.length()-2, names_text.length()-2, sub_text.toString());
				
				return true;
			}
			catch(Exception e)
			{
				System.out.println("BRoke");
				return false;
			}
			finally{
				scanner.close();
			}
		}//End else statement.
	}
	/**
	 * This will construct a previously saved conference and load all the data 
	 * with the previous data. if there is an issue with the data such as the conference not existing, the method will return false.
	 * 
	 * The JSON formatted txt file will look like so
	 * {
	 * 	"conference":{
	 * 		"manuscripts": [{
	 * 			"author":"Example author name",
	 * 			"text":"Soon there will be a full manuscript placed here",
	 * 			"reviews":[{
	 * 				"name":"ReviewMr1", "text":"Best manuscript ever!",
	 * 				},
	 * 				{
	 * 				"name":"ReviewMr1", "text":"Best manuscript ever!",
	 * 				}
	 * 				]
	 * 			},{
	 * 			"author":"Example author name",
	 * 			"text":"Soon there will be a full manuscript placed here",
	 * 			"reviews":[{
	 * 				"name":"ReviewMr1", "text":"Best manuscript ever!",
	 * 				},
	 * 				{
	 * 				"name":"ReviewMr1", "text":"Best manuscript ever!",
	 * 				}
	 * 				]
	 * 			}],
	 * 		"users":[{ "name":"Ben", "role":"Program Chair"},
	 * 				 {"name":"Farley", "role":"Reviewer"}]
	 * 	}
	 * }
	 * of course with multiple conference object that will be saved with the
	 * conference name they specified.
	 * 
	 * precondition: my_manuscript_list.size == 0;
	 * precondition: my_user_list.size == 0;
	 * precondition: my_user == NULL;
	 * @author Anthony Sierra
	 * @version 11.20.2011
	 * @return boolean
	 * @param String the conference that was saved and is being instantiated.
	 * @throws FileNotFoundException when the file was not read.
	 */
	private boolean instantiateConference(String the_conference_name) throws FileNotFoundException
	{
		//So first we need a string to pass in to the JSON Parser
		//So lets build a string from a file name.
		StringBuilder text =
			new StringBuilder();
		Scanner scanner;
		if (test_data_on)
		{
			scanner =
				new Scanner(new FileInputStream("src/datamodels/conferencesinformation.txt"), "UTF-8");	
		}
		else
		{
			scanner =
				new Scanner(new FileInputStream("src/datamodels/datafile.txt"), "UTF-8");		
		}
		try {
			while (scanner.hasNextLine()){
				text.append(scanner.nextLine());
			}
		}
		finally{
			scanner.close();
		}
		//Okay so now we have the file in text. so now we create our JSON object
		//and start our parsing.
		try
		{
			//Create JSON File
			JSONObject my_json_parser =
			 new JSONObject(text.toString());
			JSONObject conference =
			 new JSONObject(my_json_parser.get(the_conference_name).toString());
			
			//Get Manuscript Information
			JSONArray manuscripts =
					new JSONArray(conference.get("manuscripts").toString());
			//Go through and get data about the manuscript
			for (int i = 0; i < manuscripts.length(); i++)
			{
			   //Create JSON Objects to get the information about the manuscript
				JSONObject author = 
				 new JSONObject(manuscripts.get(i).toString());
				JSONObject text_of_manuscript = 
				 new JSONObject(manuscripts.get(i).toString());
				JSONObject reviews_on_manuscript = 
				 new JSONObject(manuscripts.get(i).toString());
				JSONArray manuscript_reviews = 
				 new JSONArray(reviews_on_manuscript.get("reviews").toString());
				
				//Instantiate the manuscript with the above retrieved data
				Manuscript temp = 
					new Manuscript(new User(author.get("author").toString()),
							       text_of_manuscript.get("text").toString());
				//Go through and get the reviews on the manuscript
				for (int j = 0; j < manuscript_reviews.length(); j++)
				{
					//Instantiate review_data
					JSONObject temp_review_data =
						new JSONObject(manuscript_reviews.get(i).toString());
					Review temp_review =
						new Review(temp_review_data.get("name").toString(),
								   temp_review_data.get("text").toString());
					//add review to manuscript
					temp.addReview(temp_review);
				}
				//add manuscript to global manuscript list.
				my_manuscript_list.add(temp);
			}
			//Get all of the users associated with the conference
			JSONArray users = new JSONArray(conference.get("users").toString());
			for (int i = 0; i < users.length(); i++)
			{
				JSONObject user = new JSONObject(users.get(i).toString());
				User temp_user = new User(user.get("name").toString());
				//I just modify this since i don't see that you are doing anything with the role
				//add the roll to each user.
				String temp_role = user.get("role").toString();
				if ( temp_role.equals("Author")) {
					temp_user.setCurrentRole(Role.AUTHOR);
				}
				else if ( temp_role.equals("Program Chair"))
				{
					temp_user.setCurrentRole(Role.PC);
				}
				else {
					temp_user.setCurrentRole(Role.REVIEWER);
				}
				my_user_list.add(temp_user);
			}
			return true;
		}
		catch(Exception the_e)
		{
			System.out.println("Unable to parse file");
			return false;
		}
	}
	public boolean equals(Conference the_conference)
	{
		boolean same = false;
		int correct = 0;
		if (my_manuscript_list.equals(the_conference.getManuscripts()))
		{
			correct++;
		}
		if (my_user_list.equals(the_conference.getUsers()))
		{
			correct++;
		}
		if (my_name.equals(the_conference.getName()))
		{
			correct++;
		}
		if (correct == 3)
		{
			same = true;
		}
		return same;
	}
	
}
